home *** CD-ROM | disk | FTP | other *** search
- Safe Zones in IBM BASIC
- (COMPUTE! Magazine July 1986)
-
- There is a way to store a few characters or flags in the PC's
- memory that will survive the BASIC RUN command. BASIC's CLEAR command
- gives you the ability to create a safe area of RAM of almost any size.
- Besides deleting all variables, CLEAR controls the amount of memory
- available to BASIC. By adding a command and a parameter to the CLEAR
- command, you can make the BASIC workspace smaller than usual, reserving
- the extra memory for yourself. The workspace is initially 65,536 bytes
- but it's easy to reserve some memory at the top of that space. Use
- this format:
-
- CLEAR ,workspace
-
- where workspace is a number less than 65536. To calculate the correct
- value, subtract from 65536 the number of bytes you want to protect.
- For instance, the command, CLEAR ,65280 reserves the last 256 bytes
- (65536 - 256 = 65280) of BASIC workspace for your use. When you type
- RUN after a CLEAR statement like this, the size of the workspace is
- reset to its default but the data in the reserved area is not affected.
- As long as the next program begins with a similar CLEAR statement, it
- can PEEK into the reserved area and find the values that the previous
- program POKEd there. Here's a simple program that stores some values
- in a 256-byte reserved area:
-
- 10 CLEAR ,65280
- 20 FOR A=0 TO 255
- 30 POKE A+65280,A
- 40 NEXT
-
- After you run the program, enter and run this program to read the
- stored values back:
-
- 10 CLEAR ,65280
- 20 FOR A=0 TO 255
- 30 PRINT PEEK(A+65280)
- 40 NEXT
-
- -----------------------------------------------------------------
- Selective BSAVE/BLOAD
- (PC Magazine Vol 5 No 13 July 1986 User-to-User)
-
- Most users who BSAVE and BLOAD BASICA screens do so a full screen
- at a time, but it can be very handy to do it in smaller pieces. The
- LITLBSAV.BAS program BSAVEs a little piece of the screen (three lines)
- and then lets the user BLOAD it back in various places up and down the
- screen. This technique works very well off a RAMdisk or hard disk but
- is slow when run from a floppy.
- Editor's Note: The program was modified so it BSAVEd three lines
- (a line of text with a blank line above and below) and let users move
- the BSAVEd block up and down the screen. (Including blank lines above
- and below the printed line effectively erases existing printed lines
- on-screen.) In line 120 the program determines whether the system is
- monochrome (where PEEK(1097)=7) or not, and in line 130 sets the
- segment to &HB800 for color or &HB000 for mono. Color systems offer
- four screen pages, 0 through 3. If you have a color system, you can
- increase the upper limit in line 200 to 3680 and make the text
- temporarily "disappear."
- The nice thing about this technique is that it lets you "pop" up
- text onto existing screens. However, it won't restore the existing
- part of the screen it covers over. Still, by BSAVEing portions of
- screens and BLOADing them at the appropriate locations, you save disk
- space adn make the BLOAD operation a little faster.
- Since color screen memory is not dual-ported (as mono memory is),
- you'll see "chatter" or "snow" while the BLOAD is occurring. Most snow
- is white, so by setting a white (7) background most of it is covered
- up. This will run slower on a disk system unless you hit the Up and
- Down Arrow keys rapidly enough to keep the floppy spinning constantly.
- These days you can buy slow hard disks for a lot less than $500. Or
- stock up on system RAM and try this in a RAMdisk.
- BSAVCALC.BAS calculates the offset and length for BSAVEs (and the
- offset for BLOADs) less than a full screen in size. The PC text screen
- memory is arranged so that each character takes up 2 bytes -- one
- representing the actual character, and one for the character's
- attribute. The default text screen is 80 characters wide, so each
- 80-wide lien in memory takes up 160 bytes. Color memory begins at
- segment &HB800, mono memory at &HB000. You tell BASICA which segment
- you want with the statement DEF SEG=&HB800 or DEF SEG=&HB000. BSAVE
- needs to know three things -- the filename it will use to store the
- screen on your disk, the "offset" (distance in bytes up from the
- segment specified by DEF SEG), and the length of the file to save.
- Line 1 goes from offset 0 to offset 159, line 2 from 160 to 319, etc.
- All BLOAD needs to know is the filename and offset, not the length.
-
- 100 'LITLBSAV.BAS
- 110 DEFINT A-Z:CLEAR:S$=STRING$(4,205)
- 120 DEF SEG=0:IF PEEK(1097)=7 THEN SG=&HB000 ELSE SG=&HB800
- 130 DEF SEG=SG:KEY OFF:SCREEN 0,0:COLOR 4,7,6:CLS:LOCATE 2,1,0
- 140 PRINT S$;" This BLOADs a line at a time (hit ";CHR$(24):" and ";
- 150 PRINT CHR$(25);" keys to move, or ESC to end) ";S$
- 160 BSAVE "TEST.SCR",0,480:CLS:S=3680:GOTO 210
- 170 I$=INKEY$:IF I$="" THEN 170 ELSE IF I$=CHR$(27) THEN LOCATE 1,1:END
- 180 I=INSTR("HP",RIGHT$(I$,1)):IF I=0 OR LEN(I$)=1 THEN BEEP:GOTO 210
- 190 IF I=1 THEN IF S<0 THEN BEEP:GOTO 170 ELSE S=S-160:GOTO 210
- 200 IF S>3520 THEN BEEP:GOTO 170 ELSE S=S+160
- 210 BLOAD "TEST.SCR",S:GOTO 170
-
- - - - - -
- 100 'BSAVCALC.BAS
- 110 DEF FNST$(Z)=MID$(STR$(Z),2+(Z<0)):Q$=CHR$(34):CLS
- 120 PRINT "Pick one: 1 - BSAVE 2 - BLOAD (1 or 2)"
- 130 I$=INKEY$:IF I$="" THEN 130 ELSE IF I$=CHR$(13) THEN END
- 140 IF INSTR("12",I$)=0 THEN 130 ELSE I=VAL(I$)
- 150 IF I=2 THEN B$="BLOAD " ELSE B$="BSAVE "
- 160 PRINT CHR$(30);B$;"information:";STRING$(20,32)
- 170 INPUT "Enter a start line from 1-25: ",S1
- 180 IF S1<1 OR S1>25 THEN BEEP:GOTO 170
- 190 IF I=2 THEN PRINT:PRINT "For line";S1:GOTO 230
- 200 INPUT "Enter a stop line from 1-25: ",S2
- 210 IF S2<1 OR S2>25 OR S2<S1 THEN BEEP:GOTO 200
- 220 PRINT:PRINT "For line(s)";S1;"to";S2
- 230 OFFSET=(S1-1)*160:LENGTH=(S2*160)-OFFSET
- 240 PRINT "Offset =";OFFSET:IF I=2 THEN 260
- 250 PRINT "Length =";LENGTH
- 260 PRINT "Syntax = ";B$;Q$;"filename";Q$;",";
- 270 PRINT FNST$(OFFSET);:IF I=2 THEN 290
- 280 PRINT ",";FNST$(LENGTH);
- 290 PRINT:PRINT:PRINT STRING$(40,61):PRINT:GOTO 120
-
- -----------------------------------------------------------------
- Value Added
- (PC Magazine Vol 5 No 13 July 1986 User-to-User)
-
- In the IBM BASICA documentation for VAL, the example at the bottom
- of the page correctly extracts the house number from an address:
-
- PRINT VAL("3408 SHERWOOD BLVD.")
- 3408
-
- However, if the address happens to be "3408 E 9th Street," VAL returns
- the number 3048000000000, as it interprets the "E" as the exponential
- part of the number. This also occurs with a D.
- You can prevent trouble by putting periods after the E or D.
-
- PRINT VAL("3408 E. 9th Street")
-
- works properly.
-
- -----------------------------------------------------------------
- Automatic IBM Screen Printing
- (COMPUTE! Magazine August 1986)
-
- You can add a Print Screen function to any program by POKEing a
- tiny machine language into a reserved space at the top of BASIC's
- memory area. The ML just executes INT5:RETF to call the Print Screen
- routine and returns to BASIC.
- When incorporating this routine into your program(s), the line
- with the CLEAR statement must be the first line in your program.
- Otherwise, any previously defined variables will be erased. Once the
- machine language is POKEd into memory, your program can execute the
- statement CALL PRTSC to make a printout.
-
- 100 CLEAR ,&HFFF0:PRTSC=&HFFF0
- 110 DEF SEG:FOR X=0 TO 2:READ N:POKE X+PRTSC,N:NEXT
- 120 DATA &HCD,&H05,&HCB
- 200 CALL PRTSC
-
- -----------------------------------------------------------------
- Batch Files with IBM BASIC
- (COMPUTE! Magazine August 1986 by Lawrence H. Bannister)
-
- IBM users know that you can save time by using the batch commands
- of DOS to perform a sequence of DOS commands automatically. But the
- austere language of DOS provides only three variations of one simple
- IF statement and has no practical way at all of manipulating strings
- or performing arithmetic. It's difficult to write a batch file that
- creates neat screen displays, makes logical branches, allows user
- input, and traps errors.
- A more flexible technique is to call DOS commands or even batch
- files from with a BASIC program. This frees you from the limitations
- of batch files and takes advantage of the string and arithmetic
- functions of BASIC.
- You can call DOS from BASIC as often as you wish by using the
- SHELL command found in IBM BASICA. Although it is not documented,
- this command is implemented in version 2.1 or higher of DOS. Aside
- from a few small problems to be avoided, its possibilities are limited
- only by your imagination.
- To demonstrate some of these possibilities, the BASIC Batch Demo
- program below displays two menus of options, interprets the user's
- responses, and then calls a variety of DOS routines in several
- different ways. The Batch File for Demo is a short batch file that
- is required as part of this demonstration.
- When you run the BASIC program, it shows a menu offering four
- choices:
-
- MENU A:
- 1. Show system date
- 2. Show system time
- 3. Show system date and time
- 4. None of the above
- Enter your choice:
-
- When the user presses a key, the program checks to see if the
- keypress was 1, 2, 3, or 4, and if so, uses the SHELL command to call
- the appropriate DOS function: DATE, TIME, or the batch file that calls
- both DATE and TIME.
- When DOS returns control to BASIC, the program displays a second
- menu:
-
- MENU B:
- 1. Run Checkdisk
- 2. Show Disk Directory
- 3. None of the above
- Enter your choice:
-
- This is similar to the first menu, except this time the program
- calls a DOS function that requires a parameter to be passed to the DOS
- command line. The BASIC program asks the user for the necessary
- information, then concatenates the appropriate command-line string.
- Notice that the SHELL command can pass either a literal string,
- as done in the first menu, or a string variable, as in the response
- to the second menu.
- There are two considerations to keep in mind when using this
- technique. First, make sure your system has enough memory. Although
- DOS, BASICA, and your BASIC program can be loaded into a machine with
- as little as 64K of RAM, you won't have much memory left over to do
- anything very useful. At least 92K RAM is desireable, because DOS and
- BASICA together use about 90K if that much is available. You need
- still more memory if you also want to run a batch file that calls a
- lengthy program like EDLIN.
- Second, be sure not to create a sequence that is reentrant or
- recursive. For example, the result will be unpredictable if you BASIC
- program calls a batch file that, in turn, calls BASIC. Reentrant
- sequences of this nature are apt to cause a system crash that can be
- remedied only by turning off the power.
- A minor aggravation is that DOS scrolls 25 lines on the screen
- while BASIC scrolls only 24 lines due to the function key display on
- the 25th line. Furthermore, BASIC and DOS each maintain an independent
- pointer to the screen position of the cursor. These differences can
- cause BASIC PRINT statements to overwrite something that DOS has just
- printed.
- To avoid this problem, always start the BASIC program with the
- KEY OFF command to turn off BASIC's function key display. Then use a
- CLS command each time that DOS returns control to BASIC, or, as shown
- in the sequence following the second menu in the BASIC Batch Demo
- program, surround the SHELL commands with LOCATE 24,1 statements and
- two blank PRINT lines to ensure that both DOS and BASIC always start
- scrolling from the bottom of their own screens.
-
- BASIC Batch Demo Program:
-
- 1000 'Procedure Description
- 1010 'Clear screen and display a menu offering four choices
- 1020 'Wait for user response
- 1030 'If user response is not valid
- 1040 'Then : display error message and repeat the menu
- 1050 'Else :
- 1060 'Invoke the selected DOS function or Batch file
- 1070 'Clear screen and display a second menu
- 1080 'Wait for user response
- 1090 'If user response is not valid
- 1100 'Then : display error message and repeat the menu
- 1110 'Else :
- 1120 'Invoke the selected DOS function or program
- 1130 '
- 1140 '
- 1150 KEY OFF:CLS
- 1160 GOTO 1210
- 1170 '
- 1180 PRINT 'Error message
- 1190 PRINT "* * * * * * * ILLEGAL RESPONSE ^ REDO"
- 1200 '
- 1210 PRINT:PRINT "MENU A:" 'Display menu
- 1220 PRINT:PRINT "1. Show system date"
- 1230 PRINT:PRINT "2. Show system time"
- 1240 PRINT:PRINT "3. Show system date and time"
- 1250 PRINT:PRINT "4. None of the above"
- 1260 PRINT:PRINT:INPUT "Enter your choice: ",A$
- 1270 '
- 1280 IF A$="" THEN 1180 'Check response
- 1290 IF ASC(A$)<49 THEN 1180
- 1300 IF ASC(A$)>52 THEN 1180
- 1310 '
- 1320 IF A$="1" THEN SHELL "DATE"
- 1330 IF A$="2" THEN SHELL "TIME"
- 1340 IF A$="3" THEN SHELL "PROG2"
- 1350 '
- 1360 CLS
- 1370 GOTO 1410
- 1380 '
- 1390 PRINT "* * * * * * * ILLEGAL RESPONSE ^ REDO"
- 1400 '
- 1410 PRINT:PRINT "MENU B:"
- 1420 PRINT:PRINT "1. Run Checkdisk"
- 1430 PRINT:PRINT "2. Show Disk Directory"
- 1440 PRINT:PRINT "3. None of the above"
- 1450 PRINT:PRINT:INPUT "Enter your choice: ",A$
- 1460 PRINT
- 1470 '
- 1480 IF A$="" THEN 1390
- 1490 IF ASC(A$)<49 THEN 1390
- 1500 IF ASC(A$)>51 THEN 1390
- 1510 '
- 1520 IF A$="3" THEN 1630
- 1530 IF A$="1" THEN B$="CHKDSK"
- 1540 IF A$="2" THEN B$="DIR"
- 1550 INPUT "Enter drive letter: ",C$
- 1560 IF C$="" THEN 1550
- 1565 X=ASC(C$+CHR$(0)):IF X<65 OR X>66 THEN 1550
- 1570 D$=B$+LEFT$(C$,1)+":"
- 1580 LOCATE 24,1
- 1590 IF A$="1" THEN GOSUB 1710
- 1600 SHELL D$
- 1610 PRINT:PRINT
- 1620 '
- 1630 PRINT "End of BASICA program, returning to SYSTEM"
- 1640 PRINT
- 1650 PRINT TAB(20) "Normally would return to SYSTEM here,"
- 1660 PRINT TAB(20) "but for debug and demo purposes the"
- 1670 PRINT TAB(20) "program will restart after a delay"
- 1680 FOR I=1 TO 5000:NEXT I:RUN
- 1690 '
- 1700 '
- 1710 PRINT
- 1720 PRINT "WARNING: You will get error message `Bad command ...'"
- 1730 PRINT " if the called program is not on "
- 1740 PRINT " the disk in the default drive"
- 1750 RETURN
-
-
- Batch File for Demo:
-
- ECHO OFF
- ECHO .
- REM Display the system date
- DATE
- ECHO .
- REM Display the system time
- TIME
- :ENDPROG2
-
- -----------------------------------------------------------------
- BASIC Debugging
- (PC Magazine August 1986 User-to-User)
-
- BASIC is great for interactive programming, but its debugging
- tools are quite primitive. One of the most irritating limitations is
- that when you make a simple correction to a single line (even a REMark)
- BASIC flushes all your variables, closes all your files, and forces you
- to start the program over to test the correction.
- When the interpreter finds an error, it prints an error message
- and halts the program. In many cases, you could continue running the
- program if only you could re-enter the offending line and re-execute
- it. To make such on-the-fly corrections, examine the erroneous line
- with the LIST command. (The problem line will already be displayed if
- it contains a syntax error.) Then type the following command in
- direct mode:
-
- CHAIN MERGE "CON",ERL,ALL
-
- The cursor will drop down to the next line and wait for keyboard
- input. Next, rekey the bad line, and press Enter and then Ctrl-Z and
- then Enter again. The program will continue where it left off. The
- next time you list or save the program, it will contain the repaired
- program line.
- Another tip on smart BASIC debugging is to avoid error traps (ON
- ERROR GOTO) unless they are absolutely necessary. They tend to hide
- errors that need to be caught, and you will find yourself unable to
- get to the root of a malfunction. Programs can trap errors right at
- the source, and then turn error trapping off as soon as possible.
- For example:
-
- 100 'Print report
- 110 ON ERROR GOTO 130
- 120 GOTO 150
- 130 PRINT "Printer ERROR. Hit a key."
- 140 WHILE INKEY$="":WEND:RESUME
- 150 LPRINT "ABC Company Report"
- 160 ON ERROR GOTO 0
- 170 '...print rest of report ....
-
- This example assumes that any printer errors will surface during
- the printing of the first line of a report. The error trap itself
- resides directly above the possible error, and error trapping is on
- only during the printing of that line. Use a similar layout when
- opening files. Printer and disk I/O are about the only places that
- an error trap is really needed. You can write program code to test
- for any other potential problems without resorting to BASIC's error
- handling.
- Editor's Note: Using CHAIN MERGE "CON" to fix a BASIC problem
- without shutting down the active program is a handy trick. Your
- cursor may temporarily disappear while you're entering the new line,
- and you may have to hit the Esc key to erase a message on the screen
- before you type in the CHAIN MERGE... command, but the technique can
- save a tremendous amount ot time. Note that while this will correct
- the problem line in memory, be sure to save the file to disk to make
- the correction permanent.
- In the report-printing routine, you might want to test the error
- that BASIC catches with an IF ERR=25 THEN... or IF ERL=150 THEN... to
- make sure that the actual problem isn't falsely reported as a printer
- error when it's caused by something else. However, it is right to
- trap all the usual errors by writing thorough code, not by skimping
- on traps and waiting for a mistake to fall through to an ON ERROR
- statement.
-
- -----------------------------------------------------------------
- Refreshing PAUSE
- (PC Magazine August 1986 User-to-User)
-
- To pause for a keystroke in BASICA, most programmers use either
-
- 10 A$=INEKY$:IF A$="" THEN 10
-
- or
-
- 10 WHILE INKEY$:WEND
-
- A more natural way is to create a machine language subroutine at the
- beginning of your program and then call it whenever required. Simply
- insert the following code at the start of any program:
-
- 0 CLEAR,5888
- 1 DEF SEG=5888
- 2 FOR X.=0 TO 6
- 3 READ Y.
- 4 POKE X.,Y.
- 5 NEXT
- 6 PAUSE=0
- 7 DATA 80,180,7,205,33,88,203
-
- and then adda a
-
- 100 CALL PAUSE
-
- (substituting the appropriate line number for the 100) whenever you
- want to wait for a keystroke. The example here takes up seven lines,
- but you can use colons to concatenate it all to a single line starting
- with 0 and save the line as an ASCII file, then merge this file into
- any of your existing programs. The X. and Y. variables and line number
- 0 are uncommon so that they don't interfere with ones already in your
- programs.
- The key you hit to break the pause is not stored in the keyboard
- buffer after the program execution continues. If you need to read the
- key, change the "7" to a "1" in the DATA statement in line 7.
- Editor's Note: This may be more natural than the usual methods,
- but it doesn't really work any better and won't compile as is. If you
- try it and do want the keystroke to print, after changing the 7 to 1
- in the DATA statement, follow the CALL PAUSE with a
-
- 200 PRINT INKEY$
-
- (substituting the appropriate line number for the 200).
-
- -----------------------------------------------------------------
- Compaq Unprotection
- (PC Magazine August 1986 User-to-User)
-
- It's simple to modify the technique for unprotecting BASIC
- programs described in PC Mag Vol 4 No 25 User-to-User and PC Mag Vol 5
- No 10 PC Tutor to work on non-IBM versions of BASIC. Instead of IBM's
- location 1124, use 1228 for Compaq BASIC 2.11, and 1433 for Compaq
- BASIC 3.11. If the location is included in the BSAVE ooperation, you
- may omit it from the BLOAD. Other non-IBM, non-Compaq versions of
- MS-BASIC may use entirely different locations.
- Editor's Note: "Protecting" a BASIC file by saving it with the
- ",p" option doesn't really do much other than prevent naive users from
- listing the source code. The technique to remove the flimsy protection
- is to get into BASIC and typing:
-
- BSAVE "UN.P",1124,1
-
- (substituting location 1228 or 1433 if you're using Compaq BASIC 2.11
- or 3.11, respectively). If you every try to list a BASIC program and
- see an "Illegal function call" message, just type:
-
- BLOAD "UN.P"
-
- At this point you should be able to list the source code. If not, make
- sure you tried the proper offset (1228 or 1433) for the BASIC version
- you're using. Then resave the formerly protected BASIC program to
- remove the effects of the ",p" permanently.
-
- -----------------------------------------------------------------
- STRING$ and CHR$
- (COMPUTE! Magazine September 1986)
-
- The statement PRINT STRING$(15,32) has exactly the same effect as
- PRINT " " (15 spaces). STRING$ can be used where any
- long series of identical characters is needed. For instance, PRINT
- STRING$(40,46) prints a line consisting of 40 dots.
- You can also do the same thing through concatenation. To create
- a string consisting of 30 spaces, for instance, use:
-
- SP$=" "
- FOR J=1 TO 30
- SP$=SP$+CHR$(32)
- NEXT
-
- This construction is easy to type and requires only a few more
- characters than printing the string in literal form.
-
- -----------------------------------------------------------------
- BASIC Configuration
- (PC World September 1986 Star-Dot-Star)
-
- A short BASIC program can define BASIC's function keys and then
- erase itself from memory. A short batch file can start BASIC and run
- this program automatically so that your custom function key assignments
- are in place.
- Defining the function key settings in this manner also lets you
- use the following time-saving trick. Whenever you write a BASIC
- program, always put a comment on line 1 beginning with the program's
- name enclosed in quotes. Combining this step with the F10 definition
- show in BSTART.BAS enables you to save a program anytime with one
- quick keystroke.
- The first part of F10's definition, "LIST 1"+CHR$(13), simply
- lists the first line of the current program -- the line containing the
- program's name. The two CHR$(30) characters move the cursor back to
- the beginning of the listed line. SAVE overwrites the line number and
- the apostrophe, leaving the file name in quotation marks intact. The
- last CHR$(13) simulates pressing Enter, executing the SAVE command
- using the supplied file name.
- This technique should be a boon to anyone who issues SAVE commands
- frequently, since it reduces that task to a single keystroke. If you
- prefer to save your programs in ASCII format you can place the ,A after
- whatever file name you specify.
-
- -----------------------------------------------------------------
- IBM Custom Characters
- (COMPUTE! Magazine September 1986)
-
- You can redefine the character set on the IBM PC; however, there
- are a couple of restrictions. Redefined characters must be printed on
- one of the graphics screens to be seen, and only the upper half of the
- character set (characters 128-255) can be changed. The following
- program shows how to redefine CHR$(128) as an alien shape. It displays
- the custom character on SCREEN 1.
-
- 10 DEF SEG=0
- 20 POINTER=&H7C 'POINTER &H110 for characters 0-127 on the PCjr only
- 30 FOR VECTOR=0 TO 3:OLDVEC(VECTOR)=PEEK(POINTER+VECTOR):NEXT
- 40 DEF SEG=&H1700
- 50 FOR DOTPOS=0 TO 7:READ DOT DATA:POKE DOTPOS,DOTDATA:NEXT
- 60 DEF SEG=0:
- 70 SCREEN 1:CLS
- 80 FOR VECTOR=0 TO 2:POKE(POINTER+VECTOR),0:NEXT:POKE POINTER+3,&H17
- 90 PRINT CHR$(128)
- 100 FOR VECTOR=0 TO 3:POKE(POINTER+VECTOR),OLDVEC(VECTOR):NEXT
- 110 DATA 60,126,90,126,60,36,66,129
-
- You make the computer look to RAM rather than ROM for its character
- data. If you have at least 128K of RAM in your PC, memory above 96K is
- unused by BASIC and is thus a safe place to store the custom character
- data. Line 40 of the program accesses this area with the statement
- DEF SEG=&H1700. In line 50, the program puts the alien shape data in
- the area beginning at &H1700. Line 110 contains the data.
- To make the PC fetch its character data from the segment at &H1700,
- we must change certain pointers at the bottom of memory. These pointers
- are four bytes long. The first two bytes represent an offset to the
- segment address contained in the third and fourth bytes. The pointer
- to the data for the built-in graphics and foreign language characters
- (numbered 128-255) is at locatino &H7C. Since the program redefines a
- character in this range -- CHR$(128) -- we've used this pointer value
- in line 20. On the PCjr, you can redefine characters in the range
- 0-127 using the pointer at location &H110. In order to access either
- character data pointer, you must set DEF SEG to zero since the pointers
- are at the bottom of memory. The program does this in lines 10 and 60.
- Before the program ends, the character data pointers must be
- restored to their default values. If you end the program with the
- character pointers still modified, the computer can't recognize the
- custom characters and will fail to respond to any commands. Before
- modifying the characters, save the default character set pointers
- (line 30). When you're done printing the custom characters, restore
- the pointers to their original values (line 100).
-
- -----------------------------------------------------------------
- Identifying Displays
- (PC Magazine Vol 5 No 16 Sept 30, 1986 PC Tutor)
-
- A user develops applications with the BASIC interpreter and
- compiles them with Microsoft QuickBASIC. He uses a technique to blank
- the screen while text is being written to it. This results in a nice,
- professional-looking video screen that flashes on all at once, rather
- than visibly being drawn one line at a time. To turn the display off,
- use the statement:
-
- OUT 984,1
-
- and to turn it back on:
-
- OUT 984,41
-
- This works perfectly with an IBM or compatible color graphics
- adapter. The problem is that the programs must also run on some
- Hercules Graphics Cards (and Hercules clones), and the technique
- doesn't work with these boards. Different video pages are also used
- in the programs, and these, too, are ignored by the Hercules card.
- Editor's Note: This technique won't work on regular IBM Mono
- Adapters, either. The port being manipulated is the "Mode Control
- Port Register," which has a different address on color adapters and
- monochrome adapters, including the Hercules Graphics Card. The Control
- Port for monochrome displays is at address 952 rather than 984. (In
- hex, these addresses are 3B8 and 3D8.)
- You can blank an IBM Monochrome Adapter or Hercules Card with:
-
- OUT 952,1
-
- and unblank it with:
-
- OUT 952,41
-
- but that's not the best way to do it.
- The control port address is always 4 higher than the I/O address
- of the 6845 video chip. That port address is a word (2 bytes) stored
- at the hex address 0040:0063 in the BIOS data area. So, you can
- define a variable for the Control Port thus:
-
- DEG SEG=&H40
- CTRLPORT=4+256*PEEK(&H64)+PEEK(&h63)
-
- Now you can simply use the variable CTRLPORT instead of 984 or 952.
- You won't be able to use separate video pages on an IBM Monochrome
- Adapter or the Hercules Graphics Card, however; so unless you want to
- write alternative code for the monochrome boards, it's easier to avoid
- using video pages altogether. (If you must use video pages, you can
- still use the value of CTRLPORT to also identify the type of adapter.)
- In general, however, the best way for your programs to identify
- the video display is to ask the user on-screen. This is nothing to
- be ashamed of. You'll find that most software that does anything
- beyond plain vanilla text output requires some sort of installation
- program. Some really big-league stuff like Microsoft Word can adapt
- to different displays without being told, but then we're talking about
- a 44K WORD.COM program (version 3.0) that identifies displays and
- provides drivers for them. We're also talking about problems by
- experts in the field. Further, we're about to see a real explosion
- in video adapters, and it's going to get tougher and tougher to write
- programs that work with all of them. The EGA is just the beginning.
- (The above technique of blanking the screen won't work on an EGA, but
- it won't do any harm, either.) This is one reason why the graphics
- device interface of Microsoft Windows is so important to the future
- of the PC. Windows takes on the responsibility of dealing with the
- hardware so that you can concentrate on the program.
-
- -----------------------------------------------------------------
- BSAVE Image Arrays to Disk
- (PC World October 1986 The Help Screen)
-
- Recording a BASIC image array in a disk file and reading that
- file to set an image variable is simpler than using GET and PUT. To
- save an image array to disk, issue the DEF SEG statement to set BASIC's
- data segment as the current memory segment, and execute the BSAVE
- (binary save) command.
- The BSAVE command, which saves any portion of memory to disk,
- requires three parameters: the filespec of the file being saved, the
- offset (number of bytes) into the current memory segment where the
- first byte of data representing the image begins, and the number of
- bytes to be saved.
- The filespec requires a file name, but it can include a drive
- specifier and, with BASIC 2.0 and later versions, a path. The offset
- should point to the beginning of the image array variable. You
- accomplish this by specifying the array's first element, (0), with the
- VARPTR function. You already know the size of the variable array
- because you had to calculate the number of bytes that the image array
- required to properly DIMension the array. In this example, the image
- is 34 bytes. Because a single-precision array dedicates 4 bytes per
- element, a nine-element array will reserve sufficient space.
- BSAVE.BAS also demonstrates how to load a saved image array.
- Issue a DEF SEG statement to set BASIC's data segment as the current
- memory segment, then execute the BLOAD (binary load) command to put
- the image data into memory. BLOAD requires just two parameters: the
- filespec and the offset of the current memory segment where the image
- file should be placed. Point to the beginning of the image array
- variable with the aid of the VARPTR function.
-
- BSAVE.BAS:
-
- 10 SCREEN 1:CLS
- 20 LINE (0,0)-(10,10),3,B
- 30 CIRCLE (5,5),5,1
- 40 PAINT (5,5),2,1
- 50 DIM IMAGE(22)
- 60 GET (0,0)-(10,10),IMAGE
- 70 DEF SEG
- 80 BSAVE "IMAGE.FIL",VARPTR(IMAGE(0)),88
- 90 ERASE IMAGE
- 100 DIM IMAGE(22)
- 110 DEF SEG
- 120 BLOAD "IMAGE.FIL",VARPTR(IMAGE(0))
- 130 PUT (100,100),IMAGE
- 140 LOCATE 13
-
- -----------------------------------------------------------------
- Personalized DATA
- (PC Magazine Vol 5 No 20 Nov 25, 1986 User-to-User)
-
- STAMP.BAS (PC Mag Vol 5 No 8 April 29, 1986) demonstrated how to
- modify a comment permanently from within a BASIC program. It's also
- possible to modify a quoted string in an assigned statement or DATA
- statement, since the BASIC interpreter will set up the string variable
- to point into the program itself when the string is assigned to, or
- read to, a string variable.
- UPDATER.BAS asks for the user's name, displaying the name that is
- already loaded in the DATA statement as the default. If the user then
- simply hits the Return key, the program accepts the default; otherwise
- the program stores the replacement name in the DATA statement and then
- saves itself. CVI is used to for the string, since this technique
- avoids possible overflow errors that can result from multiplication.
- Editor's Note: This kind of trick can come in handy when adding
- new information on the fly, but be careful with it since it can also
- write bad data over good data. You can get around this by adding a
- line to the program that saves a backup "UPDATER.BAK" file to disk
- before it makes any of the changes in memory and then writes the
- permanently changed file.
-
- 100 'UPDATER.BAS
- 110 READ DUMMY$
- 120 PRINT "Enter your name: [";DUMMY$;"]"
- 130 LINE INPUT I$
- 140 IF I$="" THEN END ELSE I$=I$+SPACE$(19)
- 150 P%=VARPTR(DUMMY$)
- 160 L%=PEEK(P%)
- 170 A%=CVI(CHR$(PEEK(P%+1))+CHR$(PEEK(P%+2)))
- 180 FOR I%=1 TO L%
- 190 POKE A%+I%-1,ASC(MID$(I$,I%))
- 200 NEXT
- 210 SAVE "UPDATER
- 220 DATA "User name goes here"
-
- -----------------------------------------------------------------
- BASIC and the Environment
- (PC Magazine Vol 5 No 20 Nov 25, 1986 PC Tutor)
-
- You can use the undocumented feature of batch files that allows
- treating environment strings as replaceable parameters. With this
- you can let batch files know which device drivers are currently loaded
- and to prevent running incompatible resident programs. For instance,
- to load a mouse driver, your AUTOEXEC.BAT file can execute:
-
- SET MOUSE=1
-
- Then you can do things in batch files like:
-
- IF "%MOUSE%"="1" some command
- IF NOT "%MOUSE%"="1" some other command
-
- Getting at the environment in BASIC is different.
-
- Editor's Note: This is a good use of the environment, except it
- doesn't work right under DOS 3.0. DOS 2.x, 3.1 and 3.2 handle it fine.
- The segment address of the environment is always stored at offset
- &H002C of the Program Segment Prefix (PSP) of any program. So, if you
- could find the segment address of BASICA.COM's PSP (which will be
- different depending on which resident programs and device drivers were
- loaded), you could directly access the environment with PEEK. This
- would be messy and probably involve some assembly language routines.
- There's a better way, and that is to upgrade to DOS 3.1 or later.
- The new BASICA 3.0 ENVIRON$ function retrieves strings from the
- environment based either on the parameter name (such as "PATH") or on
- a number. The small program below shows both approaches. The WHILE
- loop in the first part displays the same information as the DOS SET
- command executed without parameters.
-
- 10 I=1
- 20 WHILE ("" <> ENVIRON$(I))
- 30 PRINT ENVIRON$(I)
- 40 I=I+1
- 50 WEND
- 60 PRINT "The COMSPEC is ";ENVIRON$("COMSPEC")
-
- -----------------------------------------------------------------
- Doing a DIR in BASIC
- (PC Magazine Vol 5 No 20 Nov 25, 1986 PC Tutor)
-
- How do you read a diskette directory information into an array
- from a BASIC program, and how do you invoke a Print-Screen from within
- a program automatically?
-
- Editor's Note: A very common method used by BASIC programmers for
- reading the directory is no more elegant than:
- 1) Clear the screen with CLS
- 2) Do a FILES command to display a directory on the screen
- 3) Read the information off the screen character by character with
- a combination of the LOCATE statement and teh SCREEN function. (The
- SCREEN function reads characters from the screen; there is also a
- SCREEN statement used for setting video modes.)
- If you'd rather not have the users of your program know what you're
- doing, you can use the COLOR statement to set the same foreground and
- background colors so nobody can see the FILES display. (The information
- is still there, of course.)
- You might also consider another method using the SHELL command,
- which is documented under BASIC 3.0 and works most of the time under
- BASIC 2.0. The SHELL command executes another program or a DOS command
- from BASIC. Your line would read:
-
- SHELL ("DIR > DIRLIST")
-
- This puts a normal DIR listing into a file called DIRLST. You can then
- read the DIRLIST file normally and extract the information you want.
- Other than these approaches, you'd probably have to use an assembly
- language subroutine. This would definitely be more complex than either
- of the two methods described above. BASIC is not the only high-level
- language that has no built-in facility for obtaining directory
- information: Turbo Pascal and Microsoft C 3.0 don't either.
- Doing a Print-Screen from a BASIC program is much easier. In fact,
- the BASIC 3.0 manual shows two methods for doing it in Appendix B on
- assembly language subroutines. The BIOS Print Screen routine is invoked
- by an Interrupt 5, which in assembly language takes just two bytes:
- &HCD and &H05. An assembly language routine in BASIC needs only one
- more byte, an &HCB, which is a far return back to the main BASIC
- program. You can determine the bytes needed for an assembly language
- routine by going into DEBUG assemble mode with the A command and
- typing:
-
- INT 5
- RETF
-
- and then listing the bytes with the D command.
- To get these bytes into a BASIC listing, first DIMension an integer
- array and store the assembly language code in it:
-
- 10 DIM APRTSC%(2)
- 20 APRTSC%(1)=&H05CD
- 30 APRTSC%(2)=&H90CB
-
- Each integer can store 2 bytes. (Note that the integers are stored in
- reverse order, with the most significant byte higher in memory.) The
- extra &H90 at the end is a NOP instruction, which does nothing.
- After the array is set up, use the VARPTR function to find the
- address of the array in memory and store it in another variable:
-
- 40 PRTSC%=VARPTR(APRTSC%(1))
-
- Now you need only CALL that variable:
-
- 50 CALL PRTSC%
-
- and your screen will be printed.
-
- -----------------------------------------------------------------
- IBM PC One-Liner
- (COMPUTE! December 1986 by Paul W. Carlson)
-
- Programs don't have to be long to be useful. The one-line program
- below can be used to entertain pre-schoolers, while teaching them the
- alphabet and the computer's keyboard at the same time. Adults can
- benefit from the program by gaining an increased understanding of how
- characters are produced on the IBM's video display. However it's used,
- the program is certainly worth the time it takes to type in the single
- line.
- When you run it, nothing seems to happen. Now press any key on
- the keyboard. A giant character matching the key you pressed rises
- from the bottom of the screen and centers itself on the display.
- Press another key. The same thing happens and continues happening
- until you press Ctrl-Break.
- The program enlarges all the letters (uppercase and lowercase),
- symbols, and punctuation that appears on the keyboard -- plus a few
- that don't appear on the keycaps. If you press Ctrl along with a
- letter or number key, you'll see one of the IBM's graphics characters.
- Even the function keys produce results. Try pressing F1.
- Despite its small size, the program contains some techniques you
- may find useful in other programs.
- 1. The program begins by setting the segment to location $FFA6.
- This is 14 bytes before the PEL (character definition) map in ROM.
- The program reads your keystroke and converts it to the corresponding
- ASCII code.
- 2. Then the program loops through eight bytes for the character,
- with byte zero (the first byte) containing the bits for the top row of
- the character and byte seven containing those for the bottom row. It
- stores the value of the PEL map in the variable A and initializes A$
- as a null string.
- 3. We begin to loop through the eight bits of the current byte,
- resting the rightmost bit first. The variable M equals one if the bit
- is set and equals zero if it's not. The value of the variable W equals
- 32 (the ASCII code for a blank space) if the bit is not set and equals
- 219 (the ASCII code for a solid block) if the bit is set. Either three
- blanks or three solid blocks are added to the beginning of A$. Then
- the program shifts all bits in the current byte by subtracting the
- value of the rightmost bit and dividing by two. This step is repeated
- for each bit of the current byte.
- 4. The next step is to print A$ preceded by 28 blanks. This is
- done twice to double the character's height. Then the program
- branches back to step 2 and repeats the process for each byte of the
- PEL map that defines the character. After the last byte of the PEL
- map has been processed, we print two blank lines and return to step 1
- to wait for another keypress.
- Experienced programmers may notice that the code could be made
- even more compact. Some statements could be combined, but this would
- result in parentheses several levels deep, making the program more
- difficult to understand.
-
- 1 KEY OFF:DEF SEG=&HFFA6:L$=INPUT$(1):N=ASC(L$):CLS:LOCATE 24,1,0:FOR
- L=0 TO 7:A=PEEK(N*8+L+14):A$="":FOR J=0 TO 7:M=A AND 1:W=32+M*187:A$
- =CHR$(W)+CHR$(W)+CHR$(W)+A$:A=(A-M)/2:NEXT J:PRINT SPC(28)A$:PRINT
- SPC(28)A$:NEXT L:PRINT:PRINT:GOTO 1
-
- (NOTE: To save and run this one-line program, copy it out and make it
- one continuous line by removing the carriage returns from the ends of
- the lines.)
-
- -----------------------------------------------------------------
- Faster Slide Show
- (PC Magazine Vol 5 No 21 Dec 9, 1986 User-to-User)
-
- This technique produces a smooth BASIC slide show program. The
- BASIC BLOADer normally reads a graphics screen off a disk directly to
- the screen buffer. This approach gives a very slow (7.5-second) and
- messy screen update. However, using a combination of the PUT statement
- and VARPTR function with BLOAD creates a fast and smooth slide show
- program. Use these statements to create screen data files:
-
- 100 DIM A(4000)
- .
- . (Screen-creating code)
- .
- 200 GET (0,0)-(319,199),A
- 210 DEF SEG
- 220 ADDRESS=VARPTR(A(0))
- 230 BSAVE "SCR1.",ADDRESS,16004
-
- Then use the following statements to display the graphics screens:
-
- 100 DIM A(4000)
- 110 ADDRESS=VARPTR(A(0))
- 120 BLOAD "SCR1.",ADDRESS
- 130 PUT (0,0),A,PSET
-
- This method updates the screen in less than a second. It still
- takes about 7.5 seconds to BLOAD the graphics information into memory,
- but you can display one screen while the next one loads. The full
- technique is implemented in DEMOLOAD.BAS:
-
- 100 'DEMOLOAD.BAS
- 110 DEF FNS$(Z)=MID$(STR$(Z),2)
- 120 SCREEN 1:CLS:KEY OFF:DIM A(4000)
- 130 PRINT "First we'll make 3 screens"
- 140 PRINT "(Hit any key to continue)"
- 150 WHILE INKEY$="":WEND:CLS
- 160 FOR B=1 TO 3:FOR C=1 TO 23
- 170 PRINT STRING$(40,48+B);:NEXT
- 180 CIRCLE (160,92),60,B,,,4/5
- 190 PAINT (160,92),B
- 200 GET (0,0)-(319,199),A
- 210 DEF SEG:ADDRESS=VARPTR(A(0))
- 220 BSAVE "SCR"+FNS$(B),ADDRESS,16004
- 230 CLS:NEXT
- 240 '
- 250 PRINT "Now we'll quick-load them"
- 260 PRINT "(Hit any key to continue)"
- 270 WHILE INKEY$="":WEND
- 280 ADDRESS=VARPTR(A(0))
- 290 BLOAD "SCR1",ADDRESS
- 300 PUT (0,0),A,PSET
- 310 BLOAD "SCR2",ADDRESS
- 320 PUT (0,0),A,PSET
- 330 BLOAD "SCR3",ADDRESS
- 340 PUT (0,0),A,PSET
-
- -----------------------------------------------------------------
- BASICA 3.2 Bug
- (PC Magazine Vol 5 No 22 Dec 23, 1986 User-to-User)
-
- DOS 3.2 BASICA.COM does not save files efficiently. If a file's
- size is reduced, the space allocated is fixed at the largest previously
- saved size. This is not true for all other IBM (Microsoft) BASICs,
- including DOS 3.2 BASIC.COM. The solution is to set up a macro (based
- on the filename being imbedded in the program at a fixed location) to
- first delete the current file before the updated version is saved.
- SmartKey is a big help here.
- Editor's Note: Another solution is to add two lines to the
- beginning of your program:
-
- 101 KILL"filename
- 102 SAVE"filename
-
- (substituting the actual name of your BASICA program for filename).
- Each time you run it, this code will delete the existing version and
- save the subsequent one.
- Actually, when you chop a large program down to a smaller one,
- BASICA 3.2 not only keeps the file size the same but actually seems to
- retain the discarded part of the program. To see this in action
- (assuming you're using BASIC 3.2 only), run LONG.BAS to create a 10K
- file:
-
- 100 'CREATE.BAS -- creates a long file
- 110 DEF FNST$(Z)=MID$(STR$(Z),2+(Z<0))
- 120 OPEN "LONG.BAS" FOR OUTPUT AS #1
- 130 FOR A=100 TO 5000 STEP 10
- 140 PRINT #1,FNST$(A);" REM DUMMY TEXT"
- 150 NEXT:CLOSE:END
-
- Get into DOS and note the file size. Then get into BASICA 3.2,
- load LONG.BAS, and issue the command to get rid of most of the file's
- contents:
-
- DELETE 200-
-
- Save the shorter file, and get into DOS and you'll see that the tiny
- file has the same size as the older, larger one. Then get into DEBUG,
- and start leaning on the D key and you'll see that the part of the file
- you deleted is still there.
-